package sketch.specs;

import java.util.LinkedHashMap;
import java.util.Map;

import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.internal.core.dom.NaiveASTFlattener;

import sketch.main.SketchTestOptions;
import sketch.util.Checker;

public class RandomSequenceReplaceVisitor extends NaiveASTFlattener {

	public final Map<MethodInvocation, SimpleName> randomValues;
	
	public final Map<MethodInvocation, String> randomSequences;
	
	public RandomSequenceReplaceVisitor(Map<MethodInvocation, SimpleName> randomValues, 
			Map<MethodInvocation, String> randomSequences) {
		Checker.checkNull(randomSequences, "The randomSequences input could not be null.");
		Checker.checkNull(randomValues, "The randomValues input could not be null.");
		this.randomSequences = randomSequences;
		this.randomValues = randomValues;
		Checker.checkTrue(this.randomSequences.size() == this.randomValues.size(), "The size of two maps should be equal:" +
				" randomValues: " + randomValues.size() + ",  randomSequences: " + randomSequences.size());
	}
	
	@Override
	public boolean visit(ExpressionStatement assignmentStatement) {
		if (assignmentStatement.getExpression() instanceof Assignment) {
			Assignment assignment = (Assignment) assignmentStatement
					.getExpression();
			Expression right = assignment.getRightHandSide();
			Expression left = assignment.getLeftHandSide();

			if (left instanceof SimpleName && right instanceof MethodInvocation) {
				if(SketchTestOptions.verbose) {
				   System.out.println("assignment: " + assignment + ", parent: "
						+ assignment.getParent().getClass());
				}
				SimpleName name = (SimpleName) left;
				MethodInvocation methodInvoke = (MethodInvocation) right;
				// get the replacing seq
				String seq = this.replaceSeq(methodInvoke, name);
				if (seq != null) {
					this.buffer.append(seq);
					return false;
				}
			}
		}
		return super.visit(assignmentStatement);
	}
	
	private String replaceSeq(MethodInvocation methodInvoke, SimpleName name) {
		//this.randomSequences.containsKey(methodInvoke) && this.randomValues.containsKey(methodInvoke)
		MethodInvocation mInvoke = null;
		for(MethodInvocation m : this.randomSequences.keySet()) {
			if(m.getStartPosition() == methodInvoke.getStartPosition()) {
				mInvoke = m;
				break;
			}
		}
		SimpleName n = this.randomValues.get(mInvoke);
		Checker.checkNull(n, "The name should not be null.");
		
		if(n.toString().equals(name.toString())) {
			return this.randomSequences.get(mInvoke);
		} else {
			return null;
		}
	}
}
